'use strict'
const path = require('path')
const pkgDir = require('pkg-dir').sync
const pathExists = require('path-exists').sync
const fse = require('fs-extra')
const npminstall = require('npminstall')
const { isObject } = require('@kpzc-cli-dev/utils')
const formatPath = require('@kpzc-cli-dev/format-path')
const {
  getDefaultRegistry,
  getNpmLatestVersion
} = require('@kpzc-cli-dev/get-npm-info')
class Package {
  constructor(options) {
    if (!options) {
      throw new Error('Package类的options参数不能为空!')
    }
    if (!isObject(options)) {
      throw new Error('Package类的options参数必须是对象!')
    }
    // package目标路径
    this.targetPath = options.targetPath
    // 缓存package的路径
    this.storeDir = options.storeDir
    // package的name
    this.packageName = options.packageName
    // package的version
    this.packageVersion = options.packageVersion
    // package的缓存目录前缀
    this.cacheFilePathPrefix = this.packageName.replace('/', '_')
  }

  async prepare() {
    if (this.storeDir && !pathExists(this.storeDir)) {
      //缓存不存在生成缓存目录
      fse.mkdirpSync(this.storeDir)
    }
    if (this.packageVersion === 'latest') {
      this.packageVersion = await getNpmLatestVersion(this.packageName)
    }
    // _@imooc-cli_init@1.1.3@@imooc-cli
    // @imooc-cli/init 1.1.3
  }

  get cacheFilePath() {
    return path.resolve(
      this.storeDir,
      `_${this.cacheFilePathPrefix}@${this.packageVersion}@${this.packageName}`
    )
  }
  // 判断当前Package是否存在
  async exists() {
    if (this.storeDir) {
      await this.prepare()
      return pathExists(this.cacheFilePath)
    } else {
      return pathExists(this.targetPath)
    }
  }

  // 安装package
  async install() {
    await this.prepare()
    return npminstall({
      root: this.targetPath,
      storeDir: this.storeDir,
      registry: getDefaultRegistry(true), //发布到npm包， 可能无法同步cnpm，选择npm install
      pkgs: [
        {
          name: this.packageName,
          version: this.packageVersion
        }
      ]
    })
  }

  //更新package
  async update() {
    await this.prepare()
    //1. 获取最新的npm模块版本号
    const latestPackageVersion = await getNpmLatestVersion(this.packageName)
    //2. 查询最新版本号对应的缓存路径是否存在
    const latestFilePath = this.getSpecificCacheFilePath(latestPackageVersion)
    //3. 如果不存在更新到最新版本
    if (!pathExists(latestFilePath)) {
      await npminstall({
        root: this.targetPath,
        storeDir: this.storeDir,
        registry: getDefaultRegistry(true),
        pkgs: [
          {
            name: this.packageName,
            version: latestPackageVersion
          }
        ]
      })
      this.packageVersion = latestPackageVersion
    } else {
      //更新最新版本version
      this.packageVersion = latestPackageVersion
    }
  }
  getSpecificCacheFilePath(packageVersion) {
    return path.resolve(
      this.storeDir,
      `_${this.cacheFilePathPrefix}@${packageVersion}@${this.packageName}`
    )
  }
  //获取入口文件路径
  getRootFilePath() {
    function _getRootFile(targetPath) {
      // 1. 获取package.json 所在目录 - pkg-dirpkg-dir
      const dir = pkgDir(targetPath)
      if (dir) {
        // 2. 读取package.json -require()
        const pkgFile = require(path.resolve(dir, 'package.json'))
        // 3. main/lib -path
        if (pkgFile && pkgFile.main) {
          // 4. 路径兼容 (win 和 Mac)
          return formatPath(path.resolve(dir, pkgFile.main))
        }
        return null
      }
      return null
    }
    if (this.storeDir) {
      return _getRootFile(this.cacheFilePath)
    } else {
      return _getRootFile(this.targetPath)
    }
  }
}
module.exports = Package
